<template>
    <div style="position: relative" v-loading="!initialized">
        <div class="mce-editor-wrap">
            <textarea :id="Id" :value="richValue"></textarea>

            <import-btn
                v-if="canImport"
                class="import-btn"
                @to-import="toImport"
                >导入</import-btn
            >
        </div>

        <yanxiu-material-dialog
            ref="material-modal"
            v-model="materialModalVisible"
            :mode="1"
            :category="['img']"
            :limitSize="1 * 10 * 1024 * 1024"
            previewEnable
            showMyMaterial
            @on-ok="insertMaterialImage"
            @update:value="materialModalVisible = false"
        />
    </div>
</template>

<script>
/*eslint-disable*/
import YanxiuMaterialDialog from '@/components/yanxiu-material-dialog.vue';
import $ from 'jquery';
import uploadOss from '@/lib/upload-oss';
import ImportBtn from '@/components/mceEditor/import-word-btn.vue';
import { ElMessage } from 'element-plus';
const Tinymce = require(`/public/static/ruiyun2-mooc-web/plugins/tinymce/tinymce.js`);
window.$ = window.jQuery = $;

const { getUploadToken, getFileKey } = uploadOss;
// const Tinymce = require("./assets/tinymce/tinymce.js");
window.tinymce.baseURL = `${process.env.BASE_URL}static/ruiyun2-mooc-web/plugins/tinymce`;
const MceEditor = {
    name: 'mce-editor',
    // model: {
    //   prop: 'value',
    //   event: 'on-change'
    // },
    data() {
        const Id = Date.now();
        return {
            initialized: false,
            isInit: false, // 是否初始化完数据
            uploadData: {
                host: ''
            },
            materialModalVisible: false,
            materialTypes: [],
            Id,
            Editor: null,
            defaultConfig: {
                // GLOBAL
                language: 'zh_CN',
                height: 300,
                theme: 'modern',
                resize: false, // 禁止拉伸
                menubar: false,
                branding: false, // 去除右下角的'由tinymce驱动'
                elementpath: false, // 左下角的当前标签路径
                relative_urls: false, // 关闭自动将 url 转为相对路径。由于相对路径在 App 上无法识别
                remove_script_host: false, // 同上
                link_title: false, // 关闭传入链接的标题，即鼠标上浮显示的文本
                default_link_target: '_blank', // 插入链接都使用新窗口打开
                target_list: false, // 关闭打开方式选项
                paste_preprocess: function (plugin, args) {
                    var content = args.content;
                    content = content.replace(
                        /<a[\s\S]*?>[\s\S]*?<\/a>/gi,
                        function (aTag) {
                            if (!/target="_blank"/i.test(aTag)) {
                                if (/target=/i.test(aTag)) {
                                    return aTag.replace(
                                        /^target="\S*?"/i,
                                        'target="_blank"'
                                    );
                                } else {
                                    return aTag.replace(
                                        /^<a\s/,
                                        '<a target="_blank" '
                                    );
                                }
                            }
                            return aTag;
                        }
                    );
                    args.content = content;
                },
                toolbar: 'fontselect | customImage | link | table | hr | fontsizeselect bold italic underline forecolor | bullist numlist | alignleft aligncenter alignright alignjustify | undo redo kityformula',
                plugins: `
            paste
            importcss
            image
            code
            table
            advlist
            link
            lists
            textcolor
            colorpicker
            hr
            kityformula
          `,

                // CONFIG

                forced_root_block: 'p',
                force_p_newlines: true,
                importcss_append: true,

                // CONFIG: ContentStyle 这块很重要， 在最后呈现的页面也要写入这个基本样式保证前后一致， `table`和`img`的问题基本就靠这个来填坑了
                content_style: `
            *                         { padding:0; margin:0; }
            html, body                { height:100%; padding:0 5px;}
            img                       { max-width:100%; height:auto; }
            a                         { text-decoration: none; }
            iframe                    { width: 100%; }
            p                         { line-height:1.6; margin: 0px; }
            table                     { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
            .mce-object-iframe        { width:100%; box-sizing:border-box; margin:0; padding:0; }
            ul,ol                     { list-style-position:inside; }
          `,

                insert_button_items: 'image link | inserttable',

                // CONFIG: Paste
                paste_retain_style_properties: 'all',
                paste_word_valid_elements: '*[*]', // word需要它
                paste_data_images: true, // 粘贴的同时能把内容里的图片自动上传，非常强力的功能
                paste_convert_word_fake_lists: false, // 插入word文档需要该属性
                paste_webkit_styles: 'all',
                paste_remove_styles_if_webkit: false,
                paste_merge_formats: true,
                nonbreaking_force_tab: false,
                paste_auto_cleanup_on_paste: false,
                // CONFIG: Font
                fontsize_formats: '10px 11px 12px 14px 16px 18px 20px 24px',

                // CONFIG: StyleSelect
                style_formats: [
                    {
                        title: '首行缩进',
                        block: 'p',
                        styles: { 'text-indent': '2em' }
                    },
                    {
                        title: '行高',
                        items: [
                            {
                                title: '1',
                                styles: { 'line-height': '1' },
                                inline: 'span'
                            },
                            {
                                title: '1.5',
                                styles: { 'line-height': '1.5' },
                                inline: 'span'
                            },
                            {
                                title: '2',
                                styles: { 'line-height': '2' },
                                inline: 'span'
                            },
                            {
                                title: '2.5',
                                styles: { 'line-height': '2.5' },
                                inline: 'span'
                            },
                            {
                                title: '3',
                                styles: { 'line-height': '3' },
                                inline: 'span'
                            }
                        ]
                    }
                ],

                // FontSelect
                font_formats: `
            微软雅黑=微软雅黑;
            宋体=宋体;
            黑体=黑体;
            仿宋=仿宋;
            楷体=楷体;
            隶书=隶书;
            幼圆=幼圆;
            Andale Mono=andale mono,times;
            Arial=arial, helvetica,
            sans-serif;
            Arial Black=arial black, avant garde;
            Book Antiqua=book antiqua,palatino;
            Comic Sans MS=comic sans ms,sans-serif;
            Courier New=courier new,courier;
            Georgia=georgia,palatino;
            Helvetica=helvetica;
            Impact=impact,chicago;
            Symbol=symbol;
            Tahoma=tahoma,arial,helvetica,sans-serif;
            Terminal=terminal,monaco;
            Times New Roman=times new roman,times;
            Trebuchet MS=trebuchet ms,geneva;
            Verdana=verdana,geneva;
            Webdings=webdings;
            Wingdings=wingdings,zapf dingbats`,

                // Tab
                tabfocus_elements: ':prev,:next',
                object_resizing: true,

                // Image
                imagetools_toolbar:
                    'rotateleft rotateright | flipv fliph | editimage imageoptions',

                extended_valid_elements:
                    'iframe[src|style|width|height|scrolling|marginwidth|marginheight|frameborder]'
            }
        };
    },
    props: {
        ossTokenData: {
            type: Object,
            default() {
                return {
                    moduleType: 'tempfile',
                    publicRead: true
                };
            }
        },
        value: {
            default: '',
            type: String
        },
        nowData: {
            type: Object,
            default: () => {
                return {};
            }
        },
        nowDataKey: {
            type: String,
            default: ''
        },
        config: {
            type: Object,
            default: () => {
                return {};
            }
        },
        accept: {
            default: 'image/jpeg, image/png, image/jpg, image/gif',
            type: String
        },
        maxSize: {
            default: 52528800, // 默认限制50M
            type: Number
        },
        withCredentials: {
            default: false,
            type: Boolean
        },
        // 是否可导入
        canImport: {
            default: false,
            type: Boolean
        }
    },
    computed: {
        richValue() {
            if (!this.isInit && this.Editor && this.Editor.setContent) {
                this.Editor.setContent(this.value);
                this.isInit = true;
            }
            return this.value;
        }
    },
    watch: {
        richValue(val) {
            this.$emit('update:value', val);
            this.$emit('on-change', val);
        }
    },
    components: {
        YanxiuMaterialDialog,
        // MaterialModal,
        ImportBtn
    },
    mounted() {
        getUploadToken(this.ossTokenData, this).then((res) => {
            if (res.status.code == 200) {
                const uploadData = {
                    ...res.data
                };
                uploadData.OSSAccessKeyId = uploadData.accessKeyId;
                this.uploadData = uploadData;
            } else {
                ElMessage.error(res.message);
            }
        });
        this.initEditor();
    },
    beforeDestroy() {
        // 销毁tinymce
        this.$emit('on-destroy');
        Tinymce.remove(`#${this.Id}`);
    },
    methods: {
        toImport(data) {
            this.insertContent(data);
        },
        initEditor() {
            const self = this;

            Tinymce.init({
                // 默认配置
                ...this.defaultConfig,
                //
                init_instance_callback: function (editor) {
                    editor.on('Change', function (e) {
                        if (self.nowDataKey && self.nowData) {
                            self.nowData[self.nowDataKey] = self.getContent();
                        }
                        self.$emit('input', self.getContent());
                    });
                },
                // 图片上传
                images_upload_handler: function (blobInfo, success, failure) {
                    if (blobInfo.blob().size > self.maxSize) {
                        failure('请上传不高于50m的文件');
                    }

                    if (self.accept.indexOf(blobInfo.blob().type) >= 0) {
                        uploadPic();
                    } else {
                        failure('图片格式错误');
                    }
                    function uploadPic() {
                        const xhr = new XMLHttpRequest();
                        const formData = new FormData();
                        const uploadData = self.uploadData;
                        uploadData.key = getFileKey(
                            uploadData.path,
                            uploadData.signature,
                            blobInfo.blob().name
                        );
                        xhr.withCredentials = self.withCredentials;
                        xhr.open('POST', uploadData.host);
                        xhr.onload = function () {
                            if (xhr.status === 200 || xhr.status === 204) {
                                success(
                                    `${uploadData.host}/${uploadData.key}?x-oss-process=image/resize,w_780`
                                );
                            } else {
                                // 抛出 'on-upload-fail' 钩子
                                self.$emit('on-upload-fail');
                                failure('上传失败');
                                return;
                            }

                            // 抛出 'on-upload-complete' 钩子
                            self.$emit('on-upload-complete', [
                                success,
                                failure
                            ]);
                        };
                        for (let key in uploadData) {
                            formData.append(key, uploadData[key]);
                        }
                        formData.append('file', blobInfo.blob());
                        xhr.send(formData);
                    }
                },

                // prop内传入的的config
                ...this.config,

                // 挂载的DOM对象
                selector: `#${this.Id}`,
                setup: (editor) => {
                    editor.addButton('customImage', {
                        text: '',
                        icon: 'image',
                        onclick: function () {
                            self.materialShow();
                        }
                    });
                    // 抛出 'on-ready' 事件钩子
                    editor.on('init', () => {
                        self.initialized = true;
                        self.$emit('on-ready');
                        setTimeout(() => {
                            editor.setContent(self.value);
                        }, 500);
                    });
                    // 抛出 'input' 事件钩子，同步value数据
                    editor.on('input change undo redo', () => {
                        self.$emit('input', self.getContent());
                    });
                    // 抛出 'blur' 事件钩子，同步value数据
                    editor.on('blur', () => {
                        self.getContent();
                        self.$emit('blur-handle');
                    });
                }
            }).then(() => {
                this.Editor = Tinymce.editors[this.Id];
                this.addLinkScriptToIFrame(
                    `${process.env.BASE_URL}static/ruiyun2-mooc-web/plugins/lib-flexible/flexible.js`
                );
            });
        },
        materialShow() {
            this.materialTypes = ['image'];
            this.materialModalVisible = true;
        },
        insertMaterialImage(data) {
            for (let index = 0; index < data.length; index++) {
                const material = data[index];
                this.insertContent(
                    `<img src="${material.materialUrl}?x-oss-process=image/resize,w_780" data-mce-src="${material.materialUrl}?x-oss-process=image/resize,w_780" />`
                );
            }
        },
        setContent(content) {
            this.Editor.setContent(content);
        },
        insertContent(content) {
            this.Editor.insertContent(content);
        },
        getContent(param = {}) {
            let content = this.Editor
                ? this.Editor.getContent(param).replace(
                      /<!--[\w\W\r\n]*?-->/gim,
                      ''
                  )
                : '';
            this.$emit('update:value', content);
            this.$emit('on-change', content);
            return content;
        },
        addLinkScriptToIFrame(url) {
            const script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = url;
            this.Editor.getDoc().head.appendChild(script);
        },
    },
    install(Vue) {
        Vue.component('Mce-editor', MceEditor);
    }
};
export default MceEditor;
</script>

<style lang="scss" scoped>
.mce-editor-wrap {
    display: flex;
    .import-btn {
        flex: none;
        margin-left: 15px;
    }
}
</style>
